//
//  config.swift
//  jocool
//
//  Created by tong on 16/6/11.
//  Copyright © 2016年 zhuxietong. All rights reserved.
//

import Foundation
import UIKit
import Eelay
//import Regex

extension String{
    public var _urlEncoding:String{
        return "\(self)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "\(self)"
    }
}

extension UIViewController{
    public func appear(at controller:UIViewController?,present:NavPresentType = .defaultPush,animated:Bool=false) {
        let _ctr = controller ?? __nav
        
        switch present {
        case .defaultPush:
            if let nav = _ctr as? UINavigationController{
                nav.pushViewController(self, animated: animated)
            }else{
                _ctr.navigationController?.pushViewController(self, animated: animated)
            }
        case .backSkip(let step):
            if let ctr = self as? TypeInitController{
                ctr.presentType = .backSkip(step)
            }
            if let nav = _ctr as? UINavigationController{
                nav.pushViewController(self, animated: animated)
            }else{
                _ctr.navigationController?.pushViewController(self, animated: animated)
            }
        case .navRootPresent:
            if let nav = _ctr as? UINavigationController{
                nav.present(self, animated: animated) {
                }
            }else{
                _ctr.navigationController?.present(self, animated: animated) {}
            }
        default:
            break
        }
    }
}

public enum NavPresentType {
    case defaultPush
    case backSkip(Int)
    case navRootPresent
    case navRootPush
    
    public static func typeWith(url:String) ->NavPresentType{
        let present = AppLink.paw(link: url).params.mutable_dictionary["__present__","push"]
        if present.cg_floatValue > 0{
            return NavPresentType.backSkip(Int(present) ?? 0)
        }
        switch present {
        case "present":
            return NavPresentType.navRootPresent
        case "push":
            return .defaultPush
        default:
            return .defaultPush
        }
    }
}


extension String{
    
    public func appendURLQuery(_ params:[String:Any]) -> String {
        guard var url = URLComponents(string: "\(self)") else {
            return self
        }
        if params.keys.count < 1{
            return self
        }
        
        var querys = [URLQueryItem]()
        for (key,v) in params {
            querys.append(URLQueryItem(name: key, value: "\(v)"))
        }

        
        if let ps = url.queryItems{
            querys = querys + ps
        }
        
        url.queryItems = querys
        return url.url?.absoluteString ?? self
    }
}

public struct EeURLCreator{
    public var path:String = ""
    public var params:[String:Any]
    public init(path:String,params:[String:Any]) {
        self.path = path
        self.params = params
    }
    public var url:String{
        get{
            var ps = [String]()
            for one in params {
                let item = one.key + "=" + "\(one.value)"
                if let kv = item.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
                {
                    ps.append(kv)
                }
            }
            var _path = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
            if ps.count > 0
            {
                if _path.contains("?")
                {
                    _path = _path + "&" + ps.joined(separator: "&")
                }
                else{
                    _path = _path + "?" + ps.joined(separator: "&")
                }
            }
            return _path
        }
    }
    
    public var rawUrl:String{
        get{
            return self.url.removingPercentEncoding ?? "" //url解码
        }
    }
}


enum DefaultRouter:AppRouter {
    static func open(link: String, at: UIViewController?, present: NavPresentType?, model: NSMutableDictionary?=nil, block:RouterBlock?=nil) -> Bool {
     
  
        if link.hasPrefix("http://") ||  link.hasPrefix("https://")
        {
            let params = AppLink.paw(link: link).params.mutable_dictionary
            let ctr = WebController(urlString: link)
            ctr.mo.model = params
            return AppLink.show(at: at, controller: ctr, present: NavPresentType.typeWith(url: link), model: model, block: block)
        }
       
        
        
        switch link {
        case "login":
            EeAuthControl.getUser { (ok, msg, user) in}
            return true
        
        default:
            return false
        }
    }
}


public typealias RouterBlock = (NSMutableDictionary)->Void
public protocol AppRouter:Any{
    static func open(link:String,at:UIViewController?,present:NavPresentType?,model:NSMutableDictionary?,block:RouterBlock?)->Bool
}

public struct AppLink:AppRouter{
  
    public static var openModel:(_:NSMutableDictionary,_:UIViewController?)->Bool = {_,_ in return false}
    
    @discardableResult
    public static func open(model:NSMutableDictionary,at:UIViewController?=UIViewController.current)->Bool {
        return openModel(model,at)
    }
    
    @discardableResult
    public static func show(at:UIViewController?, controller:UIViewController?,present: NavPresentType?=nil,model: NSMutableDictionary?=nil,block:RouterBlock?=nil) -> Bool {
        var canopen = false
        
        
        let _present =  present ?? .defaultPush

        guard let ctr = controller else {
            return false
        }
        
        canopen = true

        if let tctr = ctr as? TypeInitController
        {
            tctr.presentType = _present
            
            switch _present {
            case .navRootPresent:
                let nav = NavigationController(rootViewController: ctr)
                at?.present(nav, animated: true, completion: {
                    
                })
            case .navRootPush:
                __nav.pushViewController(ctr, animated: true)

            case .defaultPush:
                if let navctr = at?.navigationController{
                    navctr.pushViewController(tctr, animated: true)
                }else{
                    __nav.pushViewController(ctr, animated: true)
                }
                                
            default:
                
                if let navctr = at?.navigationController
                {
                    navctr.pushViewController(tctr, animated: true)
                }
                else{
                    tctr.presentType = .navRootPresent
                    let nav = NavigationController(rootViewController: ctr)
                    at?.present(nav, animated: true, completion: {
                        
                    })
                }
            }
            
        }
        else{
            switch _present {
            case .navRootPresent:
                let nav = NavigationController(rootViewController: ctr)
                at?.present(nav, animated: true, completion: {
                })
            case .navRootPush:
                __nav.pushViewController(ctr, animated: true)

            case .defaultPush:
                if let navctr = at?.navigationController
                {
                    navctr.pushViewController(ctr, animated: true)
                }else{
                    __nav.pushViewController(ctr, animated: true)
                }
            default:
                
                if let navctr = at?.navigationController
                {
                    navctr.pushViewController(ctr, animated: true)
                }
                else{
                    let nav = NavigationController(rootViewController: ctr)
                    at?.present(nav, animated: true, completion: {
                    })
                }
            }
        }
        return canopen
    }
    
    
    public static func params(str:String) -> [String:String] {
        let values = str.components(separatedBy: "&")
        var dict = [String:String]()
        for one in values{
            if one.contains("=")
            {
                let ls = one.components(separatedBy: "=")
                if ls.count > 1
                {
                    dict[ls[0]] = ls[1]
                }
            }
        }
        return dict
    }
    
    
    public static var defaultRouters:[AppRouter.Type] = [DefaultRouter.self]

    public static var routers:[AppRouter.Type] = [AppRouter.Type]()
    @discardableResult
    public static func open(link: String, at: UIViewController?=UIViewController.current, present: NavPresentType?=nil, model: NSMutableDictionary?=nil, block: RouterBlock?=nil) -> Bool {
        
        var canOpen = false
//        print("routers++++ddd++O|\(AppLink.routers)")
        
        var __present = present
        if __present == nil{
            __present = NavPresentType.typeWith(url: link)
        }
        
        let routers = AppLink.routers + AppLink.defaultRouters
        print("==DDDDs=dds==oooo|\(routers)")

        for one in routers{
//            print("++++|\(one)")
//            print("____)----\(one)",url)

            if one.open(link: link, at: (at ?? UIViewController.current) , present: __present,model: model,block: block){
                
                canOpen = true
                break
            }
        }
        if (!canOpen){
            canOpen = DefaultRouter.open(link: link, at: at, present: __present,model: model)
        }
        return canOpen
    }
    
    @discardableResult
    public static func open(_ link:String,at:UIViewController?=UIViewController.current,params:[String:Any]? = nil,model:NSMutableDictionary?=nil,block:RouterBlock?=nil) -> Bool
    {
        let ps = params ?? [:]
        let url = link.appendURLQuery(ps)
        return AppLink.open(link: url, at: at, present: nil,model: model,block: block)
    }

    
    
    
    //    public static func open(link:String,at controller:UIViewController? = __controller){
    //        let info = AppLink.paw(link: link)
    //        let linkType = AppLinkType(rawValue: info.path) ?? .unkown
    //        linkType.open(link: link, at: controller, params: info.params)
    //    }
    //
    //    static public func open(message:NSMutableDictionary){
    //
    //        let msg = message.any(nodes: "extras.msg","msg", default: NSMutableDictionary())
    //        let link = msg["link",""]
    //
    //        let info = AppLink.paw(link: link)
    //        let linkType = AppLinkType(rawValue: info.path) ?? .unkown
    //        let controller = __controller
    //        linkType.open(link: link, at: controller, params: info.params)
    //
    //    }
    //
    public static func paw(link:String) -> (path:String,params:[String:Any]) {
        
//        print("paw|\(link)")
        
        guard var urlComp = URLComponents(string: link) else {
            return ("",[:])
        }
        
        var params = [String:Any]()
        if let ps = urlComp.queryItems{
            for one in ps{
                params[one.name] = one.value ?? ""
            }
        }
        let path = link
        
//        if path.hasPrefix("http://")
//        {
//            return ("http",params)
//        }
//        if path.hasPrefix("https://")
//        {
//            return ("http",params)
//        }
//
        
        return (urlComp.path,params)

        
        
//        var _link:String = link.removingPercentEncoding ?? ""//url解码
//        var params = [String:Any]()
//
//        var path = _link
//        if path.hasPrefix("http://")
//        {
//            return ("http",params)
//        }
//        if path.hasPrefix("https://")
//        {
//            return ("http",params)
//        }
//
//        if let mach = Regex("^([^\\?]+)\\?(\\S+)$").firstMatch(in: path)
//        {
//            let strs = mach.captures.map { (str) -> String in
//                return str ?? ""
//            }
//
//            if strs.count > 0{
//                path = strs.first ?? ""
//            }
//            if strs.count > 1{
//                let param_str = strs[1]
//                let values = param_str.components(separatedBy: "&")
//                for one in values{
//                    let vs = one.components(separatedBy: "=")
//                    let _name = vs.first ?? ""
//
//                    params[_name] = vs.last ?? ""
//                }
//            }
//        }
//
//        return (path,params)
    }
}

